[Chapter 36] 36.5 sendmail's exit() Status
Author: Bryan Costales & Eric Allman
Date: 1999-01-06T21:59:22Z

#

| Chapter 36 The Command Line |

## 36.5 sendmail's exit() Status

Like any other program under UNIX, sendmail can return meaningful values to the environment and thus to you. All of the possible exit values are documented in <sysexits.h> along with the values assigned to each name. Here, we provide a bit more explanation about the most commonly used names.

The relationship between each exit value and its corresponding DSN `detail` is shown in Table 30.6 in Section 30.5.2, "The error Delivery Agent". That table also summarizes the values described here.

### 36.5.1 EX_CANTCREAT Can't Write a User's File

An exit value of EX_CANTCREAT (the value 73) means that an output file could not be written to. This error generally refers to a user-specified file rather than a system- or configuration-file-specified file. Some problems that can lead to this error (without an error message) is an attempt to write to a file that has any execute bit set in its permissions, a file that has more than one link, and (if the `SafeFileEnvironment` option; see Section 34.8.58, SafeFileEnvironment, is set) a file that is not a regular file.

If the `SafeFileEnvironment` option is specified and sendmail is unable to chroot(2) into the specified directory, the following message is logged:

>     mailfile: Cannot chroot(directory)

When delivery is to a file, sendmail will log the following error if the file cannot be opened or stat(3)'d:

>     cannot open: reason here
>     cannot fstat: reason here

and the fork(2)'d child will exit with EX_CANTCREAT.

### 36.5.2 EX_CONFIG A Configuration Error

The EX_CONFIG exit value (the value 78) means that a fatal configuration problem was found, but this does not necessarily mean that the problem was found while reading the configuration file. Failure of a delivery agent to function correctly can lead to this kind of failure:

- During delivery, when a rule set 0 selection of a delivery agent fails to specify a host with the `$@` part (see Section 29.6, "Rule Set 0"), the following error is logged and the fork(2)'d child exits with EX_CONFIG:

  >     null host name for mailer

- During delivery, when `$u` appears in the argument list for an SMTP delivery agent (see Section 30.4.1.3, "$u in A="), sendmail logs the following error and the fork(2)'d child exits with EX_CONFIG:

  >     non-clever IPC

- During delivery, when an attempt is made to use an SMTP delivery agent with a version of sendmail that was compiled without SMTP support (see Section 18.8.41, SMTP), sendmail logs the following error and the fork(2)'d child exits with EX_CONFIG:

  >     deliver: need SMTP compiled to use clever mailer

Some apparent DNS errors are really configuration problems. In the following error, `hostB` is an MX record that points back to your host. The problem is that your host doesn't know that it should be accepting mail for `hostB`. The solution is to add `hostB` to your local `$=w` class (see Section 32.5.8).

>     MX list for hostB points back to ourhost

When sendmail processes MX records, it skips any records of absurd length and logs the following message:

>     Host name ourhost too long

If an MX record points to a CNAME record, the result can be serious. The first CNAME may point to a second, the second to a third, and so on. If this list is longer than the number defined by MAXCNAMEDEPTH in domain.c, the result is the following error:

>     DNS failure: CNAME loop for bad host name here

One solution is to set the `DontExpandCnames` option (see Section 34.8.18, DontExpandCnames) to false, thus causing only the first CNAME to be used as if it were an A record.

Errors in rule set numbers are sometimes only found during actual rewriting:

>     illegal ruleset number bad number here
>     rewrite: excessive recursion (max max), ruleset bad number here
>     rewrite: ruleset num: replacement $digit out of bounds
>     Unknown ruleset bad name here

The solutions to these problems should be obvious. See Chapter 29, Rule Sets, for guidance.

Note that this EX_CONFIG and EX_SOFTWARE below cause the local postmaster to get a copy of the message on the presumption that local errors can only be fixed locally.

### 36.5.3 EX_IOERR A System I/O Error Occurred

An exit value of EX_IOERR (the value 74) means that a serious operating system error occurred. This class of error relates mostly to disk I/O.

If the body of a mail message could not be read, the following error message is logged:

>     putbody: dfqid: read error

The file may have vanished because of a disk crash and may have been restored to lost+found. The qid is the queue identifier that will help you to find the `qf` file. Inside that `qf` file are an `I` line that give the inode and major and minor device numbers of the disk that held the `df` file (see Section 23.9.7, I line).

An error that occurs while writing to the pipe(2) connection to a delivery agent causes the following error to be logged and for the fork(2)'d child to exit with EX_CONFIG:

>     putbody: write error

### 36.5.4 EX_OK No Problems, All Was Fine

The EX_OK exit code (value 0) indicates that sendmail did its job and there were no errors.

Note that this should be the exit value of all the programs that sendmail runs when they succeed without errors. To illustrate, this C language code returns a random value:

>     main()
>     {
>              need a ``return 0'' here
>     }

### 36.5.5 EX_OSERR A System Resource Error

The EX_OSERR exit code (value 71) results from various operating system errors several of which are described below. In general, this exit value is accompanied by an error message describing the problem.

When sendmail is unable to get a pipe(2) connection to send the mail message to a delivery agent, it logs one of the following errors and the fork(2)'d child exits with EX_OSERR:

>     recipient... openmailer(delivery agent): pipe (to mailer)
>     recipient... openmailer(delivery agent): pipe (from mailer)

If sendmail is unable to `dup`(2) a file descriptor so that it can write to its pipe, it logs one of first three errors below. If sendmail fails to write to its transcript file (as set by the `-X` switch; see Section 26.4), it logs the last error below. In all four cases the current open file descriptors are logged as described in Section 26.3.3, "SIGUSR1 Dump States".

>     recipient... openmailer(delivery agent): cannot dup pipe file descriptor for stdout
>     recipient... openmailer(delivery agent): cannot dup stdout for stderr
>     recipient... openmailer(delivery agent): cannot dup pipe file descriptor for stdin
>     recipient... openmailer(delivery agent): cannot dup xscript file descriptor for stdout

If a delivery agent cannot be executed, sendmail logs the following error message, and the fork(2)'d child exits with EX_OSERR:

>     Cannot exec delivery agent: reason

To save (cache) information about hosts to which connections have been made, sendmail saves a copy of the file descriptors for that connection to its internal mci structures (see Section 37.5.44, -d11.1). If it cannot duplicate a file descriptor it logs one of the following messages and the fork(2)'d child exits with EX_OSERR.

>     deliver: cannot create mailer output channel, fd=file descriptor
>     deliver: cannot create mailer input channel, fd=file descriptor

When looking up the MX record for a host, the resolv library can return an absurd value. When that happens, the following message is logged and that MX record is ignored:

>     getmxrr: res_search (host) failed with impossible h_errno (bad value)

To queue a message, sendmail must save a qf file to its queue directory. If it cannot create that file, if the directory exists, and if the uid of sendmail is 0, then the following error message will be logged and the fork(2)'d child will exit with EX_OSERR:

>     Cannot create "qf file" in "directory" (euid=uid): reason

### 36.5.6 EX_OSFILE A Critical System File Failure

The EX_OSFILE exit code (value 72) results when certain system files could not be opened and when certain system programs could not be executed.

When sendmail gets a SIGHUP signal, it attempts to re-execute itself (see Section 26.3.2, "SIGHUP Restart"). If it fails, the following error is logged and sendmail exits:

>     could not exec /path/sendmail: reason

The sendmail program can run a program to look up a `key` in a database. If sendmail fails to run the program, it prints the following error:

>     prog_map_lookup(program) failed (reason) - closing

We probably don't have to mention this, but the sendmail program has to read its configuration file. If it fails to open, stat, or read that file or if that file is not a plain file, it prints one of the following errors:

>     cannot open
>     cannot fstat
>     not a plain file
>     I/O read error

and exits with an EX_OSFILE value.

### 36.5.7 EX_SOFTWARE An Internal Software Error

The EX_SOFTWARE exit code (value 70) indicates that a software error occurred.

When sendmail has successfully connected to a remote host, it checks to see whether it knows to whom it connected. If for some strange reason it doesn't know, it logs this error and drops the connection, and the fork(2)'d child exits with EX_OSERR:

>     deliver: no host name

When figuring out whether or not to speak SMTP, sendmail looks to see whether the `$u` macro is present in the `A=` equate for the selected delivery agent (see Section 30.4.1.3). If `$u` is absent, sendmail will speak SMTP. If sendmail was compiled without SMTP support (see Section 18.8.41), the following error is logged and the fork(2)'d child exits with an EX_SOFTWARE exit code:

>     SMTP style mailer not implemented

When fork(2)s and exec(2)s a delivery agent to perform delivery, it calls wait(2) to wait for the delivery agent to exit. If the call to wait(2) fails, sendmail logs the following error and the fork(2)'d child exits with an EX_SOFTWARE exit code:

>     endmailer delivery agent name: wait

When sendmail first starts to run (provided that it is not in rule-testing mode), it performs a chdir(2) into its queue directory. If that chdir(2) fails, sendmail logs the following error and exits with an EX_SOFTWARE exit code:

>     cannot chdir(directory)

The sendmail program can run a program to look up a `key` in a database. After running that program, sendmail calls wait(2) to wait for the program to exit. If the call to wait(2) fails, sendmail prints the following error and the fork(2)'d child exits with an EX_SOFTWARE exit code:

>     prog_map_lookup(program): wait error reason

When bouncing mail, sendmail tries to set the sender to `Postmaster` if no sender can be determined. Before it can use that address (`Postmaster`), it has to parse it with rules to select a delivery agent. If that parsing fails, sendmail logs the following error and the fork(2)'d child exits with an EX_SOFTWARE exit code:

>     Cannot parse Postmaster!

When the sending of an error message results in an error, an attempt is made to send notification of that error to the address defined by the `DoubleBounceAddress` option (see Section 34.8.21, DoubleBounceAddress). If parsing that address fails, sendmail logs the following error and the fork(2)'d child exits with an EX_SOFTWARE exit code:

>     cannot parse double bounce address

See the description of `$n` (see Section 31.10.26, $n) for another error that results in the fork(2)'d child exiting with an EX_SOFTWARE exit code.

### 36.5.8 EX_TEMPFAIL A Recoverable Error

The EX_TEMPFAIL exit code (value 75) is returned by sendmail to indicate that a temporary error has occurred. Temporary errors mean that the mail message will be put in (or remain in) the queue for the present, and another delivery attempt will be made later.

One example of this type of error occurs in looking up aliases via a network service, such as NIS. If all the servers are too busy to answer before a timeout, then sendmail should temporarily queue the message and look up the aliases later:

>     alias database unavailable

Another example occurs when there is a failure to open a file descriptor as a file pointer with fdopen(3). This can happen caching an SMTP connection:

>     cannot open SMTP client channel, fd=file descriptor

In looking up hostnames with DNS, the name server or the network might be so overloaded that the lookup will time out:

>     host: Name server timeout

DNS lookup failures can also be caused by dial-on-demand networks when the connect is not fast enough. If the delivery mode of sendmail is set by the `DeliveryMode` (`d`) option (see Section 34.8.16, DeliveryMode (d)) to `defer`, that failed connection is deemed temporary.

Normally, delivery agents exit because they have finished delivering the email. If one exits because of a received signal, sendmail logs the following message and the fork(2)'d child exits with an EX_TEMPFAIL exit code:

>     mailer delivery agent name died with signal signal in octal

Also, if the `-X` command-line switch (see Section 26.4) was used to specify a transcript file, the arguments to the delivery agent will be recorded in that file.

### 36.5.9 EX_UNAVAILABLE A Resource

The EX_UNAVAILABLE error code (value 69) indicates that some system resource is unavailable. Several examples follow.

If the body size of an incoming message is larger than the size limit imposed by the `M=` equate (see Section 30.4.7, M=) the following error is reported:

>     Message is too large; M= bytes max

All delivery agent programs must be designed to return an exit value that is defined in <sysexits.h>. If a misdesigned delivery agent exits with some other value, sendmail will issue this error and consider the delivery to have failed:

>     unknown mailer error decimal representation of the error value

When delivering to a file, sendmail forks, and the child performs the actual delivery. If that child dies because of a signal, the parent logs this error:

>     child died on signal decimal representation of the signal value

To queue a message, sendmail must save a qf file to its queue directory. If it cannot open that file and if the error is other than that the file already exists, the following error message will be logged and the fork(2)'d child will exit with EX_UNAVAILABLE:

>     queuename: cannot create file in directory (euid=userid)

### 36.5.10 EX_USAGE A Command Was Used Incorrectly

The EX_USAGE error code (value 64) means that a command or configuration line was used incorrectly.

For instance, the sendmail daemon can be executed only by root. If anyone else tries to run it with `-bd` or `-bD`, the following error is printed and sendmail exits with an EX_USAGE error:

>     Permission denied

Clumsy fingers can also cause problems. If a command-line switch is used that is unknown to sendmail, the following error will be printed and sendmail will exit with an EX_USAGE code:

>     sendmail: illegal option - bad option here

In parsing an address, that address can be rejected if it contains control characters:

>     Address contained invalid control characters

If the `EightBitMode` (`8`) option (see Section 34.8.22, EightBitMode (8)) is specified with a bad character, the following error is printed and sendmail exits with an EX_USAGE code:

>     Unknown 8-bit mode bad character

If the `DeliveryMode` (`d`) option (see Section 34.8.16) is given a bad mode specification with a bad character, sendmail will print the following message and exit with an EX_USAGE code:

>     Unknown delivery mode bad mode here

36.4 Processing the Command Line |  | 36.6 Pitfalls